home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
PROG_TOO
/
C027B.ZIP
/
JAS
/
GEN.C
< prev
next >
Wrap
Text File
|
1990-03-30
|
10KB
|
430 lines
/*
* Copyright (c) 1988 by Sozobon, Limited. Author: Joseph M Treat
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*/
#include "jas.h"
geninst( sp )
STMT *sp;
{
register OPERAND *op;
register char *cp;
register short nbits = 0;
register long fill = 0L;
register short emode, ereg;
OPERAND *eff[2];
int which, do_immediate = 0;
CBUF *cbp;
extern int line;
extern long newdot;
extern Optimize;
extern CBUF *generate();
findinst( sp );
eff[0] = eff[1] = (OPERAND *) NULL;
if ( sp->op0 && sp->op0->mode == O_IMM )
do_immediate = 1;
for ( cp = sp->inst->format; *cp; cp++ ) {
if ( *cp == 'o' ) {
do {
cp++;
fill = ( fill << 3 ) | ( *cp - '0' );
nbits += 3;
} while ( cp[1] >= '0' && cp[1] <= '7' );
} else if ( *cp == 'x' ) {
do {
cp++;
if ( *cp <= '9' )
fill = ( fill << 4 ) | ( *cp - '0' );
else
fill = ( fill << 4 ) | (*cp - 'a' + 10);
nbits += 4;
} while ( (cp[1] >= '0' && cp[1] <= '9') ||
(cp[1] >= 'a' && cp[1] <= 'f'));
} else if ( *cp == '0' ) {
fill = ( fill << 1 );
nbits++;
} else if ( *cp == '1' ) {
fill = ( fill << 1 ) | 1;
nbits++;
} else if ( *cp == '$' ) {
switch ( *++cp ) {
case 's':
fill = ( fill << 2 ) |
( ( sp->misc & (S_BWL) ) >> 1 );
nbits += 2;
break;
case 'c':
fill = ( fill << 4 ) | ( sp->misc >> 4 );
nbits += 4;
break;
case 'd':
fill = ( fill << 1 ) |
( ( sp->misc & 0x8 ) >> 3 );
nbits++;
break;
}
} else if ( *cp == '%' ) {
OPERAND *mp;
cp++;
if ( *cp == '0' ) {
which = 0;
op = sp->op0;
cp++;
} else if ( *cp == '1' ) {
which = 1;
op = sp->op1;
cp++;
} else if ( *cp >= 'A' && *cp <= 'Z' ) {
which = 1;
op = sp->op1;
} else /* if ( *cp >= 'a' && *cp <= 'z' ) */ {
which = 0;
op = sp->op0;
}
switch ( *cp ) {
case 'r':
fill = ( fill << 3 ) | (op->reg & 0x7 );
nbits += 3;
break;
case 'q':
fill = ( fill << 3 ) | (op->expr.value & 0x7);
nbits += 3;
do_immediate = 0;
break;
case 'k':
fill = ( fill << 8 ) | (op->expr.value & 0xff);
nbits += 8;
do_immediate = 0;
break;
case 'v':
fill = ( fill << 4 ) | (op->expr.value & 0x0f);
nbits += 4;
do_immediate = 0;
break;
case 'm':
if ( nbits % 8 )
error( line, "internal alignment" );
generate( nbits, GENSTMT, fill, (SYM *) NULL );
nbits = 0;
fill = 0L;
if ( op->mode == O_DN || op->mode == O_AN )
op->expr.value = 1L << op->reg;
op->mode = O_REGS;
mp = ( which == 0 ) ? sp->op1 : sp->op0;
if ( mp->mode == O_PRE ) {
/*
* we must reverse the bits !GAG!
*/
int i, k;
k = op->expr.value;
for ( i = 0; i < 16; i++ ) {
fill <<= 1;
if ( k & 1 )
fill |= 1;
k >>= 1;
}
generate( 16, GENVALUE, fill,
(SYM *) NULL );
fill = 0L;
} else {
generate( 16, GENVALUE, op->expr.value,
(SYM *) NULL );
}
break;
case 'd':
if (! Optimize ) {
fill <<= 8;
nbits += 8;
if ( nbits % 8 )
error( line,
"internal alignment" );
generate( nbits, GENSTMT, fill,
(SYM *) NULL);
nbits = 0;
fill = 0L;
generate( 16, GENPCREL, op->expr.value,
op->expr.psym);
break;
}
if ( nbits != 8 )
error( line, "internal alignment" );
cbp = generate(8, GENBRNCH, fill, (SYM *) NULL);
nbits = 0;
fill = 0L;
generate( 8, GENPCREL, op->expr.value,
op->expr.psym);
add_brnch( cbp, newdot );
break;
case 'D':
if ( nbits % 8 )
error( line, "internal alignment" );
generate( nbits, GENSTMT, fill, (SYM *) NULL );
nbits = 0;
fill = 0L;
generate( 16, GENPCREL, op->expr.value,
op->expr.psym);
break;
case 'L':
if ( nbits % 8 )
error( line, "internal alignment" );
generate( nbits, GENSTMT, fill, (SYM *) NULL );
nbits = 0;
fill = 0L;
generate( 16, GENVALUE, op->expr.value,
(SYM *) NULL );
break;
case 'f':
case 'e':
emode = ereg = 0;
switch ( op->mode ) {
case O_DN:
emode = 0x0;
ereg = op->reg & 0x7;
break;
case O_AN:
emode = 0x1;
ereg = op->reg & 0x7;
break;
case O_INDR:
emode = 0x2;
ereg = op->reg & 0x7;
break;
case O_POST:
emode = 0x3;
ereg = op->reg & 0x7;
break;
case O_PRE:
emode = 0x4;
ereg = op->reg & 0x7;
break;
case O_DISP:
emode = 0x5;
ereg = op->reg & 0x7;
eff[which] = op;
break;
case O_INDX:
emode = 0x6;
ereg = op->reg & 0x7;
eff[which] = op;
break;
case O_ABS:
emode = 0x7;
ereg = 0x1;
eff[which] = op;
break;
case O_PCRL:
emode = 0x7;
ereg = 0x2;
eff[which] = op;
break;
case O_PCIX:
emode = 0x7;
ereg = 0x3;
eff[which] = op;
break;
case O_IMM:
emode = 0x7;
ereg = 0x4;
break;
}
if ( *cp == 'e' ) {
fill = ( fill << 3 ) | emode;
fill = ( fill << 3 ) | ereg;
} else {
fill = ( fill << 3 ) | ereg;
fill = ( fill << 3 ) | emode;
}
nbits += 6;
break;
}
}
}
if ( nbits % 8 )
error( line, "internal alignment" );
if ( nbits ) {
generate( nbits, GENSTMT, fill, (SYM *) NULL );
nbits = 0;
}
fill = 0L;
if ( do_immediate ) {
int size;
op = sp->op0;
size = sp->misc & (S_BWL);
if ( size == S_B ) {
generate( 8, GENVALUE, 0L, (SYM *) NULL );
}
generate( size << 3, GENRELOC, op->expr.value, op->expr.psym );
}
for ( which = 0; which <= 1; which++ ) {
if ( eff[which] == (OPERAND *) NULL )
continue;
op = eff[which];
switch ( op->mode ) {
case O_DISP:
generate( 16, GENRELOC, op->expr.value, op->expr.psym );
break;
case O_INDX:
fill = op->inx & 0x0f;
fill = ( fill << 4 ) | ((op->inx & 0x10) >> 1);
generate(8, GENVALUE, fill, (SYM *) NULL );
generate( 8, GENRELOC, op->expr.value, op->expr.psym );
break;
case O_ABS:
if ( sp->inst->flags & F_PC )
generate( 16, GENPCREL, op->expr.value,
op->expr.psym );
else
generate( 32, GENRELOC, op->expr.value,
op->expr.psym );
break;
case O_PCRL:
generate( 16, GENVALUE, op->expr.value, (SYM *) NULL );
break;
case O_PCIX:
fill = op->inx & 0x0f;
fill = ( fill << 4 ) | ((op->inx & 0x10) >> 1);
generate(8, GENVALUE, fill, (SYM *) NULL );
generate( 8, GENVALUE, op->expr.value, (SYM *) NULL );
break;
}
}
}
findinst( sp )
STMT *sp;
{
register INST *ip;
register INST *jp;
ip = sp->inst;
for ( ; ; ) {
if (! inst_ok( sp ) ) {
return;
}
jp = ip+1;
if (! strcmp( jp->mnemon, ip->mnemon ) ) {
sp->inst = ip = jp;
continue;
}
break;
}
Yerror( "illegal instruction" );
}
inst_ok( sp )
register STMT *sp;
{
register INST *ip = sp->inst;
register unsigned short size;
extern Optimize;
if (! Optimize ) {
/*
* if we're not optimizing, don't change jsr's to bsr's
*/
if (! strncmp( ip->mnemon, "jsr", 3 ) )
if (! strncmp( ip->format, "x61", 3 ) )
return -18;
}
if ( ip->op0 != O_NONE && sp->op0 == (OPERAND *) NULL )
return -1;
if ( ip->op1 != O_NONE && sp->op1 == (OPERAND *) NULL )
return -2;
if ( sp->op1 && ip->op1 == O_NONE )
return -3;
if ( sp->op0 ) {
if ( ip->op0 == O_NONE )
return -4;
if ( ( sp->op0->mode & ip->op0 ) != sp->op0->mode )
return -5;
}
if ( sp->op1 ) {
if ( ip->op1 == O_NONE )
return -6;
if ( ( sp->op1->mode & ip->op1 ) != sp->op1->mode )
return -7;
}
size = sp->misc & (S_BWL);
if ( ( size & ip->size ) != size )
return -8;
if ( ip->flags & F_Q ) {
long val = sp->op0->expr.value;
if ( sp->op0->expr.psym )
return -9;
if ( val < 1 || val > 8 )
return -10;
}
if ( ip->flags & F_MQ ) {
long val = sp->op0->expr.value;
if ( sp->op0->expr.psym )
return -11;
if ( val < -128 || val > 127 )
return -12;
}
if ( ip->flags & F_TV ) {
long val = sp->op0->expr.value;
if ( sp->op0->expr.psym )
return -13;
if ( val < 0 || val > 15 )
return -14;
}
if ( ip->flags & F_TXT ) {
OPERAND *op = sp->op0;
if ( op->mode == O_DN ) /* the db$c instruction */
op = sp->op1;
switch ( op->mode ) {
case O_DISP: case O_INDX:
if ( op->expr.psym ) {
switch ( op->expr.psym->flags & SEGMT ) {
case 0: case TXT:
break;
default:
return -15;
}
}
break;
case O_ABS:
if ( op->expr.psym == (SYM *) NULL )
return -16;
switch ( op->expr.psym->flags & SEGMT ) {
case 0: case TXT:
break;
default:
return -17;
}
break;
}
}
/*
* set the default size, if none is specified
*/
if ( size == 0 )
sp->misc |= ( ip->flags & (S_BWL) );
return 0;
}